<?php
/**
 * Copyright (c) [2019] [吴跃忠]
 * [selibra] is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 * http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 */

namespace Selibra\Di;


use ReflectionClass;
use Selibra\Tools\Console;

class AnnotationRegister
{

    /**
     * @param $namespace
     * @return array
     * @throws \ReflectionException
     */
    public static function getClassAnnotations($namespace)
    {
        $reflectionClass = new ReflectionClass($namespace);
        $annotations = $reflectionClass->getAttributes();
        return array_map(fn($annotation) => get_class($annotation), $annotations);
    }


    /**
     * @param $namespace
     * @param bool $skipNullJudge
     * @return Metadata|null
     * @throws \ReflectionException
     */
    public static function getMetadata($namespace, $skipNullJudge = false)
    {
        if (!class_exists($namespace, false) && !interface_exists($namespace, false)) {
            return null;
        }
        // 获取反射类
        $reflectionClass = new ReflectionClass($namespace);
        // 异常对象不做处理
        if ($reflectionClass->isSubclassOf(\Throwable::class)) {
            return null;
        }
        $metadata = new Metadata($namespace);
        try {
            $classAttributes = $reflectionClass->getAttributes();
            $classAnnotations = array_map(function ($attribute) {
                return $attribute->newInstance();
            }, $classAttributes);

            // 读取方法注解
            $methods = $reflectionClass->getMethods();
            $methodsAnnotations = [];

            foreach ($methods as $method) {
                $methodAttributes = $method->getAttributes();
                if (!empty($methodAttributes)) {
                    $methodAnnotations = array_map(function ($attribute) {
                        return $attribute->newInstance();
                    }, $methodAttributes);
                    $methodsAnnotations[$method->getName()] = $methodAnnotations;
                }
            }

            // 读取属性注解
            $properties = $reflectionClass->getProperties();
            $propertiesAnnotations = [];
            foreach ($properties as $property) {
                $propertiesAttributes = $property->getAttributes();
                if (!empty($propertiesAttributes)) {
                    $propertyAnnotations = array_map(function ($attribute) {
                        return $attribute->newInstance();
                    }, $propertiesAttributes);
                    $propertiesAnnotations[$property->getName()] = $propertyAnnotations;
                }

            }

            // 设置元数据
            $metadata->setClassAnnotations($classAnnotations);
            $metadata->setMethodsAnnotations($methodsAnnotations);
            $metadata->setPropertiesAnnotations($propertiesAnnotations);
            $metadata->setReflectionClass($reflectionClass);

        } catch (\Throwable $exception) {
            Console::log($exception);
            return null;
        }
        return $metadata;
    }


}